#include <igl/readOFF.h>
#include <igl/readOBJ.h>
#include <igl/read_triangle_mesh.h>
#include <igl/writeOBJ.h>

#include <iostream>
#include <string>
#include <vector>

#include "myfunctions.h"

using namespace std;
using namespace Eigen;

void readConfigureFile(string configureURL, arguConfigure & argumentInfo) {

	ifstream inputConfigure(configureURL);
	if (inputConfigure) {
		inputConfigure >> argumentInfo.fileType;
		inputConfigure >> argumentInfo.workDirectory;
		inputConfigure >> argumentInfo.fileName;
		inputConfigure >> argumentInfo.h;
		inputConfigure >> argumentInfo.LaplacianWeight;
		inputConfigure >> argumentInfo.VerticesWeight;
		inputConfigure >> argumentInfo.pcaMaxNumParticleNeighbors;
		inputConfigure >> argumentInfo.pcaMaxNumVerticesNeighbors;
		inputConfigure >> argumentInfo.pcaParticleRadiusRate;
		inputConfigure >> argumentInfo.pcaVerticesRadiusRate;
		inputConfigure >> argumentInfo.LaplacianWeightRate;

		cout << "Configure:";
		cout << "file type:" << argumentInfo.fileType << endl;
		cout << "file name:" << argumentInfo.fileName << endl;
		cout << "grid length:" << argumentInfo.h << endl;
		cout << "Laplace weight:" << argumentInfo.LaplacianWeight << endl;
		cout << "Vertices weight:" << argumentInfo.VerticesWeight << endl;
		cout << "PCA max particle neighbors:" << argumentInfo.pcaMaxNumParticleNeighbors << endl;
		cout << "PCA max vertices neighbors:" << argumentInfo.pcaMaxNumVerticesNeighbors << endl;
		cout << "Particle neighbor radius rate:" << argumentInfo.pcaParticleRadiusRate << endl;
		cout << "Vertices neighbor radius rate:" << argumentInfo.pcaVerticesRadiusRate << endl;
		cout << "Laplacian weight Rate:" << argumentInfo.LaplacianWeightRate << endl;
		cout << "configure end" << endl;
	}

}

void readModelFile(std::string & filename, Eigen::MatrixXd & Vertices, Eigen::MatrixXi & Faces) {
	std::string suffixStr = filename.substr(filename.find_last_of('.') + 1);
	
	if(suffixStr == "off") {
		igl::read_triangle_mesh(filename, Vertices, Faces);
	}
	else if (suffixStr == "obj") {
		igl::read_triangle_mesh(filename, Vertices, Faces);
	}
	else; 
	return;
}


// Write mesh into .obj file
void writeIntoOBJ(string filename, const Eigen::MatrixXd & Vertices, const Eigen::MatrixXi & Faces) {
	igl::writeOBJ(filename, Vertices, Faces);
	std::cout << "write model complished!" << endl;
}

//read particles data
void readParticlData(string filename, std::vector<SlVector3>& Particles) {
	Particles.clear();

	std::ifstream input(filename, std::ios::in | std::ios::binary);
	int nparticles;
	float minx = 100000.0f;
	float maxx = -100000.0f;
	float miny = 100000.0f;
	float maxy = -100000.0f;
	float minz = 100000.0f;
	float maxz = -100000.0f;
	float x, y, z;
	input.read((char*)&nparticles, sizeof(int));
	float fdummy;
	for (int i = 0; i < nparticles; i++)
	{
		input.read((char*)&x, sizeof(float));
		input.read((char*)&y, sizeof(float));
		input.read((char*)&z, sizeof(float));

		input.read((char*)&fdummy, sizeof(float));

		if (x < 2.0 && x > -1.0 && y < 2.0 && y > -1.0f && z < 2.0 && z > -1.0)
		{
			Particles.push_back(SlVector3(x, y, z));
		}

	}

	cout << "Number of particles: " << Particles.size() << endl;
}